#!/usr/bin/env python

# todo
# better testing for drop response body data attributes, wait for better documentatino at drop.io
# better testing for response of methods such as delete, move, copy, wait for better documentation at drop.io

# note
# after resource heavy calls such as creating, deleting, and emptying many drops a certain
# amount of time is passed before proceeding this is to allow for processes to finish

# note
# when testing for get_drops, get_assets, get_subscriptions the number of total
# items have to exceed 30, this is because the number of drops returned from the dropio api
# come in 'pages' of 30 items

# note
# not tested here:
# pingbacks
# output_locations for create file
# get_simple_upload_form
# contents of download original
# download_asset_original_file save to original file name
# convertions

__author__ = "jimmyorr@gmail.com (Jimmy Orr), chedbrandh@gmail.com (Christofer Hedbrandh)"

import os
import unittest
import argparse
import time
import random

from dropio import client
import client_test_drop
import client_test_asset
import client_test_subscription
import client_test_utils

if __name__ == "__main__":
    parser = argparse.ArgumentParser()
    parser.add_argument('api_key',
        help = 'API key to account used for testing')
    parser.add_argument('--api_key2',
        help  ='API key to second account used for permissions testing')
    parser.add_argument('--secure_api_key',
        help = 'secure API key to account used for testing request signing')
    parser.add_argument('--secure_api_key2',
        help = 'secure API key to second account used for testing request signing')
    parser.add_argument('--secure_api_key_secret',
        help = 'API key secret for secure API key to account used for testing request signing')
    parser.add_argument('--secure_api_key_secret2',
        help = 'API key secret for secure API key to second account used for testing request signing')
    parser.add_argument('--api_url',
        help = 'base url used for most api calls', default = client._API_URL)
    parser.add_argument('--upload_url',
        help = 'url used for api upload calls', default = client._UPLOAD_URL)
    parser.add_argument('--test_suite',
        help = 'test suite to be run', default = 'QUICK', choices = ['EXHAUSTIVE', 'QUICK'])
    parser.add_argument('--test_names',
        help = 'name of tests to be run', nargs = '*')
    parser.add_argument('--available_drop_name',
        help = 'available name given to drops created during testing', default = 'python_api_test')
    parser.add_argument('--available_drop_name2',
        help = 'second available name given to drops created during testing', default = 'python_api_test2')

    args = parser.parse_args()
    
    assert (args.secure_api_key is None) == (args.secure_api_key_secret is None), \
        "both secure_api_key and secure_api_key_secret must be specified when using secure keys"
    assert (args.secure_api_key2 is None) == (args.secure_api_key_secret2 is None), \
        "both secure_api_key2 and secure_api_key_secret2 must be specified when using secure keys"
    
    test_params_dict = {}
    
    # todo ugly hack start
    # http://stackoverflow.com/questions/1842168/python-unit-test-pass-command-line-arguments-to-setup-of-unittest-testcase
    # pass parameters to test case via module globals
    client_test_utils.test_params_dict = test_params_dict
    # todo ugly hack end

    # set clients
    test_params_dict['client'] = client.DropIoClient(api_key = args.api_key,
        api_url = args.api_url, upload_url = args.upload_url)
    test_params_dict['client2'] = client.DropIoClient(api_key = args.api_key2,
        api_url = args.api_url, upload_url = args.upload_url) if args.api_key2 else None
    test_params_dict['secure_client'] = client.DropIoClient(api_key = args.secure_api_key,
        api_secret = args.secure_api_key_secret, api_url = args.api_url,
        upload_url = args.upload_url) if args.secure_api_key else None
    test_params_dict['secure_client2'] = client.DropIoClient(api_key = args.secure_api_key2,
        api_secret = args.secure_api_key_secret2, api_url = args.api_url,
        upload_url = args.upload_url) if args.secure_api_key2 else None
    # set available drop names
    test_params_dict['available_drop_name'] = args.available_drop_name
    test_params_dict['available_drop_name2'] = args.available_drop_name2
    
    # todo when individual namespaces are implemented this procedure can be improved greatly
    # check availablility of available_drop_name and available_drop_name2
    drop1 = test_params_dict['client'].create_drop(drop_name = test_params_dict['available_drop_name'])
    drop2 = test_params_dict['client'].create_drop(drop_name = test_params_dict['available_drop_name2'])
    test_params_dict['client'].delete_drop(drop = drop1)
    test_params_dict['client'].delete_drop(drop = drop2)
    assert drop1.name == test_params_dict['available_drop_name'], \
        "specified drop name '%s' is not available" % test_params_dict['available_drop_name']
    assert drop2.name == test_params_dict['available_drop_name2'], \
        "specified drop name '%s' is not available" % test_params_dict['available_drop_name2']
    
    test_case_list = [
        client_test_drop.DropIoClientDropActionsTestCase,
        client_test_asset.DropIoClientAssetActionsTestCase,
        client_test_subscription.DropIoClientSubscriptionActionsTestCase,
        ]
    
    test_suite = unittest.TestSuite()
    # populate test_suite
    if args.test_names:
        for test_name in args.test_names:
            for test_case in test_case_list:
                if hasattr(test_case, test_name):
                    test_suite.addTest(test_case(test_name))
    elif args.test_suite == 'EXHAUSTIVE':
        assert test_params_dict['client'] and test_params_dict['client2'] and \
            test_params_dict['secure_client'] and test_params_dict['secure_client2'], \
            'two keys plus two secure keys with their key secrets are required to run EXHAUSTIVE test'
        for test_case in test_case_list:
            test_suite.addTests(unittest.defaultTestLoader.loadTestsFromTestCase(test_case))
    elif args.test_suite == 'QUICK':
        test_suite.addTest(client_test_drop.DropIoClientDropActionsTestCase('test_create_drop'))
        test_suite.addTest(client_test_drop.DropIoClientDropActionsTestCase('test_get_drop_self_valid_drop_name'))
        test_suite.addTest(client_test_drop.DropIoClientDropActionsTestCase('test_update_drop'))
        test_suite.addTest(client_test_drop.DropIoClientDropActionsTestCase('test_delete_drop'))
        
        test_suite.addTest(client_test_asset.DropIoClientAssetActionsTestCase('test_create_link'))
        test_suite.addTest(client_test_asset.DropIoClientAssetActionsTestCase('test_create_note'))
        test_suite.addTest(client_test_asset.DropIoClientAssetActionsTestCase('test_create_file_document_doc'))
        test_suite.addTest(client_test_asset.DropIoClientAssetActionsTestCase('test_create_file_image_jpg'))
        test_suite.addTest(client_test_asset.DropIoClientAssetActionsTestCase('test_create_file_from_url_image_gif'))
        test_suite.addTest(client_test_asset.DropIoClientAssetActionsTestCase('test_update_asset_link'))
        test_suite.addTest(client_test_asset.DropIoClientAssetActionsTestCase('test_delete_asset_file_image_jpg'))
        test_suite.addTest(client_test_asset.DropIoClientAssetActionsTestCase('test_copy_asset_file_image_jpg'))
        test_suite.addTest(client_test_asset.DropIoClientAssetActionsTestCase('test_move_asset_file_image_jpg'))
        test_suite.addTest(client_test_asset.DropIoClientAssetActionsTestCase('test_download_asset_original_file'))

        test_suite.addTest(client_test_subscription.DropIoClientSubscriptionActionsTestCase('test_create_subscription_by_subscription'))
        test_suite.addTest(client_test_subscription.DropIoClientSubscriptionActionsTestCase('test_get_subscription'))
        test_suite.addTest(client_test_subscription.DropIoClientSubscriptionActionsTestCase('test_delete_subscription'))
    
    result = client_test_utils.DropIoTextTestRunner(verbosity = 3).run(test_suite)
    
    exit(0 if result.wasSuccessful() else 1)
